﻿using Core;
using Core.Data;
using Core.Domain.Customers;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;

namespace Services.Customers
{
    /// <summary>
    /// 用户服务实现类
    /// </summary>
    public partial class CustomerService : ICustomerService
    {
        #region Fields

        private readonly IRepository<Customer> _customerRepository;
        private readonly IRepository<CustomerRole> _roleRepository;
        private readonly CustomerSettings _customerSettings;

        #endregion

        #region Ctor

        public CustomerService(
            IRepository<Customer> customerRepository,
            IRepository<CustomerRole> roleRepository,
            CustomerSettings customerSettings)
        {
            this._customerRepository = customerRepository;
            this._roleRepository = roleRepository;
            this._customerSettings = customerSettings;
        }

        #endregion

        #region Method
        /// <summary>
        /// 获取所有用户
        /// </summary>
        /// <returns></returns>
        public virtual IPagedList<Customer> GetAllCustomers(int[] customerRoleIds = null,
            string email = null, string username = null,
            string Name = null,
            string phone = null,
            int pageIndex = 0, int pageSize = 2147483647)
        {
            var query = _customerRepository.Table;
            query = query.Where(c => !c.Deleted);
            if (!String.IsNullOrWhiteSpace(email))
                query = query.Where(c => c.Email.Contains(email));
            if (!String.IsNullOrWhiteSpace(username))
                query = query.Where(c => c.Username.Contains(username));
            if (!String.IsNullOrWhiteSpace(Name))
            {
                query = query.Where(c => c.Username.Contains(Name));
            }
            //search by phone
            if (!String.IsNullOrWhiteSpace(phone))
            {
                query = query.Where(c => c.Phone == phone);
            }

            query = query.OrderByDescending(c => c.CreatedOn);

            var customers = new PagedList<Customer>(query, pageIndex, pageSize);
            return customers;
        }

        /// <summary>
        /// 获取在线用户
        /// </summary>
        /// <param name="customerRoleIds"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public virtual IPagedList<Customer> GetCustomers(int pageIndex, int pageSize)
        {
            var query = _customerRepository.Table;
            query = query.Where(c => !c.Deleted);            

            var customers = new PagedList<Customer>(query, pageIndex, pageSize);
            return customers;
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="customer">Customer</param>
        public virtual void DeleteCustomer(Customer customer)
        {
            if (customer == null)
                throw new ArgumentNullException("customer");

            if (customer.IsSystemAccount)
                throw new Exception("系统用户,不能删除");

            customer.Deleted = true;

            if (_customerSettings.SuffixDeletedCustomers)
            {
                if (!String.IsNullOrEmpty(customer.Email))
                    customer.Email += "-DELETED";
                if (!String.IsNullOrEmpty(customer.Username))
                    customer.Username += "-DELETED";
            }

            UpdateCustomer(customer);
        }

        /// <summary>
        /// 根据主键获取用户信息
        /// </summary>
        /// <param name="customerId"></param>
        /// <returns></returns>
        public virtual Customer GetCustomerById(int customerId)
        {
            if (customerId == 0)
                return null;

            return _customerRepository.GetById(customerId);
        }

        /// <summary>
        /// 根据主键集合获取用户信息
        /// </summary>
        /// <param name="customerIds"></param>
        /// <returns></returns>
        public virtual IList<Customer> GetCustomersByIds(int[] customerIds)
        {
            if (customerIds == null || customerIds.Length == 0)
                return new List<Customer>();

            var query = from c in _customerRepository.Table
                        where customerIds.Contains(c.Id)
                        select c;
            var customers = query.ToList();
            //sort by passed identifiers
            var sortedCustomers = new List<Customer>();
            foreach (int id in customerIds)
            {
                var customer = customers.Find(x => x.Id == id);
                if (customer != null)
                    sortedCustomers.Add(customer);
            }
            return sortedCustomers;
        }

        /// <summary>
        /// 根据Guid获取用户信息
        /// </summary>
        /// <param name="customerGuid"></param>
        /// <returns></returns>
        public virtual Customer GetCustomerByGuid(Guid customerGuid)
        {
            if (customerGuid == Guid.Empty)
                return null;

            var query = from c in _customerRepository.Table
                        where c.CustomerGuid == customerGuid
                        orderby c.Id
                        select c;
            var customer = query.FirstOrDefault();
            return customer;
        }

        /// <summary>
        /// 根据Email获取用户信息
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        public virtual Customer GetCustomerByEmail(string email)
        {
            if (string.IsNullOrWhiteSpace(email))
                return null;

            var query = from c in _customerRepository.Table
                        orderby c.Id
                        where c.Email == email
                        select c;
            var customer = query.FirstOrDefault();
            return customer;
        }

        /// <summary>
        /// 根据类型获取用户
        /// </summary>
        /// <param name="name"></param>
        /// <param name="method"></param>
        /// <returns></returns>
        public virtual Customer GetCustomer(string name, RegisterMethod method)
        {
            switch (method)
            { 
                case RegisterMethod.Name :
                    return GetCustomerByUsername(name);
                case RegisterMethod.Email :
                    return GetCustomerByEmail(name);
                case RegisterMethod.Phone:
                    return GetCustomerByPhone(name);
                default:
                    return GetCustomerByUsername(name);
            }
        }

        public virtual Customer GetCustomerByPhone(string phone)
        {
            if (string.IsNullOrWhiteSpace(phone))
                return null;

            var query = from c in _customerRepository.Table
                        orderby c.Id
                        where c.Phone == phone
                        select c;
            var customer = query.FirstOrDefault();
            return customer;
        }
        /// <summary>
        /// 根据用户名获取用户信息
        /// </summary>
        /// <param name="username"></param>
        /// <returns></returns>
        public virtual Customer GetCustomerByUsername(string username)
        {
            if (string.IsNullOrWhiteSpace(username))
                return null;

            var query = from c in _customerRepository.Table
                        orderby c.Id
                        where c.Username == username
                        select c;
            var customer = query.FirstOrDefault();
            return customer;
        }
        
        /// <summary>
        /// 新增用户
        /// </summary>
        /// <param name="customer"></param>
        public virtual void InsertCustomer(Customer customer)
        {
            if (customer == null)
                throw new ArgumentNullException("customer");

            _customerRepository.Insert(customer);
        }

        /// <summary>
        /// 增加匿名访客
        /// </summary>
        /// <returns></returns>
        public virtual Customer InsertGuestCustomer()
        {
            var customer = new Customer()
            {
                CustomerGuid = Guid.NewGuid(),
                Active = true,
                CreatedOn = DateTime.UtcNow,
            };

            //增加匿名权限
            var guestRole = GetCustomerRoleBySystemRole(SystemRole.Guests);
            if (guestRole == null)
                throw new Exception("'Guests' 权限没有被加载");
            customer.CustomerRole = guestRole;

            _customerRepository.Insert(customer);

            return customer;
        }

        /// <summary>
        /// 更新用户信息
        /// </summary>
        /// <param name="customer"></param>
        public virtual void UpdateCustomer(Customer customer)
        {
            if (customer == null)
                throw new ArgumentNullException("customer");

            _customerRepository.Update(customer);
        }


        /// <summary>
        /// 删除匿名用户
        /// </summary>
        public virtual int DeleteGuestCustomers(DateTime? createdFromUtc,
            DateTime? createdToUtc, bool onlyWithoutShoppingCart, int maxNumberOfRecordsToDelete)
        {

            var query = _customerRepository.Table;
            if (createdFromUtc.HasValue)
                query = query.Where(c => createdFromUtc.Value <= c.CreatedOn);
            if (createdToUtc.HasValue)
                query = query.Where(c => createdToUtc.Value >= c.CreatedOn);

            query = query.Where(c => !c.IsSystemAccount);

            query = from c in query
                    group c by c.Id
                        into cGroup
                        orderby cGroup.Key
                        select cGroup.FirstOrDefault();
            query = query.OrderBy(c => c.Id);
            var customers = new PagedList<Customer>(query, 0, maxNumberOfRecordsToDelete);


            int numberOfDeletedCustomers = 0;
            foreach (var c in customers)
            {
                try
                {
                    _customerRepository.Delete(c);
                    numberOfDeletedCustomers++;
                }
                catch (Exception exc)
                {
                    Debug.WriteLine(exc);
                }
            }
            return numberOfDeletedCustomers;
        }

        #endregion

        #region  Role
        public virtual CustomerRole GetCustomerRoleBySystemRole(string roleName)
        {

            var query = from cr in _roleRepository.Table
                        orderby cr.Id
                        where cr.SysRole == roleName
                        select cr;
            var customerRole = query.FirstOrDefault();
            return customerRole;
        }

        /// <summary>
        /// 删除权限
        /// </summary>
        public virtual void DeleteCustomerRole(CustomerRole customerRole)
        {
            if (customerRole == null)
                throw new ArgumentNullException("customerRole");

            if (customerRole.SysRole == SystemRole.Administrators || customerRole.SysRole == SystemRole.Guests || customerRole.SysRole == SystemRole.Registered)
                throw new Exception("系统权限不能删除");

            _roleRepository.Delete(customerRole);
        }

        /// <summary>
        /// 根据主键获取权限
        /// </summary>
        /// <param name="customerRoleId"></param>
        /// <returns></returns>
        public virtual CustomerRole GetCustomerRoleById(int customerRoleId)
        {
            if (customerRoleId == 0)
                return null;

            return _roleRepository.GetById(customerRoleId);
        }

        /// <summary>
        /// 获取所有权限
        /// </summary>
        public virtual IList<CustomerRole> GetAllCustomerRoles()
        {
            var query = from cr in _roleRepository.Table
                        orderby cr.Name
                        select cr;
            var customerRoles = query.ToList();
            return customerRoles;
        }

        /// <summary>
        /// 新增权限
        /// </summary>
        public virtual void InsertCustomerRole(CustomerRole customerRole)
        {
            if (customerRole == null)
                throw new ArgumentNullException("customerRole");

            _roleRepository.Insert(customerRole);
        }

        /// <summary>
        /// 更新权限
        /// </summary>
        /// <param name="customerRole">Customer role</param>
        public virtual void UpdateCustomerRole(CustomerRole customerRole)
        {
            if (customerRole == null)
                throw new ArgumentNullException("customerRole");

            _roleRepository.Update(customerRole);
        }

        #endregion

    }
}
